package com.ys.栈的链表模拟;

/**
 * 描述: 模拟栈的单链表实现
 *
 * @author CodeYang
 * @version 2020/12/26 9:43
 */
public class LinkedListStack<E> implements Stack<E> {

    /**
     * 栈顶
     * 但链表的入栈与出栈操作都在栈顶
     */
    private StackNode<E> topNode;

    /**
     * 栈节点个数
     */
    private int size;


    /**
     * 入栈操作
     * 把节点设为首节点
     *
     * @param element
     */
    @Override
    public boolean push(E element) {
        StackNode<E> node = new StackNode<>(element);
        // 判断情况
        node.next = topNode;
        topNode = node;
        size++;
        return true;
    }

    /**
     * 出栈操作
     * 也是操作栈顶
     *
     * @return
     */
    @Override
    public E pop() {
        // 判断栈是否为空
        if (isEmpty()) {
            return null;
        }
        // 不为空,"删除首届点" 移动首节点到下一个节点--抛弃原有的首节点
        // 保存一下原有数据
        E oldValue = topNode.item;
        StackNode<E> nextNode = topNode.next; // 获得下一个节点
        topNode.next = null;   // 取消原有指向
        topNode.item = null;  // 回收gc
        topNode = nextNode;   // 移动栈顶
        // 更新size
        size--;
        return oldValue;
    }

    /**
     * 查看栈顶元素
     *
     * @return
     */
    @Override
    public E peek() {
        if (isEmpty()) {
            return null;
        }

        return topNode.item;
    }

    /**
     * 判断栈是否为空
     *
     * @return 如果栈为空，则返回true；如果栈为非空，则返回false。
     */
    @Override
    public boolean isEmpty() {
        return size == 0;

    }


    private static class StackNode<E> {
        /**
         * 数据,元素
         */
        private E item;
        /**
         * next 指针
         */
        private StackNode<E> next;

        /**
         * 封装节点
         *
         * @param item
         */
        public StackNode(E item) {
            this.item = item;
        }

        public StackNode(E item, StackNode<E> next) {
            this.item = item;
            this.next = next;
        }
    }
}
